import React, { useEffect } from 'react'
import { PinterestType } from '../..'

export const Pinterest = (props: PinterestType) => {
    const { width = 860, colLength = 4, rowGap = 20, colGap = 20, mode = 'fixedGap', itemWidth = 200, children } = props
    const style: any = { '--boxWidth': `${width}px` }

    useEffect(() => {
        init()
    }, [])

    const init = () => {
        if (colLength <= 0 || width - colGap * (colLength - 1) - itemWidth * colLength < 0) {
            throw '<Pinterest> component: 参数错误'
        }
        const boxEl = document.querySelector('.x-pinterest') as HTMLElement
        const itemElList = document.querySelectorAll('.x-pinterest-item') as NodeListOf<HTMLElement>
        const itemEl = itemElList[0]
        let heightList: number[] = []
        let gap: number = colGap
        let _itemWidth: number = itemWidth

        // 定宽 | 定间距
        if (mode === 'fixedWidth') {
            // 剩余宽度
            const bn = boxEl?.offsetWidth - itemEl?.offsetWidth * colLength
            //计算真实间距
            gap = Number((bn / (colLength - 1)).toFixed(2))
        } else {
            _itemWidth = (boxEl?.offsetWidth - colGap * (colLength - 1)) / colLength
        }

        for (let i = 0; i < itemElList.length; i++) {
            const element = itemElList[i]
            element.setAttribute('style', `width: ${_itemWidth}px;`)
            const height = element.offsetHeight
            // 如果当前处在第一行
            if (i < colLength) {
                // 保存当前元素的高度。
                heightList.push(height)
                // 直接设置元素距离上部的位置和距离左边的距离。
                if (i === 1) {
                    element.setAttribute('style', `width: ${_itemWidth}px;left: ${itemEl?.offsetWidth * i}px`)
                }
                element.setAttribute('style', `width: ${_itemWidth}px;left: ${itemEl?.offsetWidth * i + gap * i}px`)
            } else {
                // 不是第一行的话，就进行比对。
                let minHeight = heightList[0] // 先保存第一项的高度
                let minIndex = 0 // 保存第一项的索引值
                for (let j = 0; j < heightList.length; j++) {
                    // 通过循环遍历比对，拿到最小值和最小值的索引。
                    if (minHeight > heightList[j]) {
                        minHeight = heightList[j]
                        minIndex = j
                    }
                }
                // 通过最小值为当前元素设置top值，通过索引为当前元素设置left值。
                if (minIndex === 0) {
                    element.setAttribute('style', `width: ${_itemWidth}px;top: ${minHeight + rowGap}px;left: ${itemEl?.offsetWidth * minIndex}px`)
                } else {
                    element.setAttribute(
                        'style',
                        `width: ${_itemWidth}px;top: ${minHeight + rowGap}px;left: ${itemEl?.offsetWidth * minIndex + gap * minIndex}px`
                    )
                }
                // 并修改当前索引的高度为当前元素的高度
                heightList[minIndex] = minHeight + rowGap + height
                // 遍历完成
                if (i === itemElList.length - 1) {
                    boxEl.style.cssText = `--boxWidth: ${width}px;height: ${Math.max.apply(null, heightList).toString() || '0'}px`
                }
            }
        }
    }

    return (
        <ul className="x-pinterest" style={style}>
            {
                // 只渲染符合规格的子组件
                findChild(children).map((item, index) => {
                    return React.cloneElement(item, { key: index })
                })
            }
        </ul>
    )
}

// 查找子组件
function findChild(children: any[]): any[] {
    let result: any[] = []
    React.Children.forEach(children, (child, index) => {
        if (child?.type?.defaultProps?.name === 'PinterestItem') {
            result.push(child)
        }
    })
    return result
}

// 子组件
export const PinterestItem = ({ children }: { children?: any }) => {
    return <li className="x-pinterest-item">{children}</li>
}

PinterestItem.defaultProps = {
    name: 'PinterestItem',
}
